package org.whh.automatic.model;

import java.io.Serializable;
import java.util.*;

/**
 * 自动任务模型类
 * <p>
 * 该类表示一个完整的自动化任务，包含以下主要组成部分：
 * 1. 任务基本信息：名称和启动文件路径
 * 2. 操作步骤列表：按顺序执行的具体操作步骤
 * 3. 动态值管理：处理任务执行过程中需要的动态输入值
 * <p>
 * 该类实现了Serializable接口以支持任务配置的保存和加载，
 * 其中动态值使用transient修饰，不参与序列化，需要在运行时设置。
 */
public class AutoTask implements Serializable {

    /**
     * 序列化版本号
     */
    private static final long serialVersionUID = 1L;

    /**
     * 任务名称
     * 用于标识和描述当前自动化任务
     */
    private String name;

    /**
     * 启动文件路径
     * 任务开始执行时需要启动的目标程序路径
     */
    private String startFilePath;

    /**
     * 程序启动等待时间（秒）
     * 启动程序后等待该时间再执行后续步骤，确保程序完全启动
     */
    private int startupWaitTime = 2; // 默认值为2秒

    /**
     * 操作步骤列表
     * 存储任务需要执行的所有步骤，按照添加顺序依次执行
     */
    private List<Step> steps = new ArrayList<>();

    /**
     * 动态值映射
     * 用于存储任务执行过程中需要的动态输入值
     * 使用transient修饰，不参与序列化，需要在运行时重新设置
     */
    private transient Map<String, String> dynamicValues = new HashMap<>();

    /**
     * 默认构造函数
     */
    public AutoTask() {
    }

    /**
     * 使用名称和启动文件路径构造任务
     *
     * @param name          任务名称
     * @param startFilePath 启动文件路径
     */
    public AutoTask(String name, String startFilePath) {
        this.name = name;
        this.startFilePath = startFilePath;
    }

    /**
     * 使用名称、启动文件路径和启动等待时间构造任务
     *
     * @param name            任务名称
     * @param startFilePath   启动文件路径
     * @param startupWaitTime 启动等待时间（秒）
     */
    public AutoTask(String name, String startFilePath, int startupWaitTime) {
        this.name = name;
        this.startFilePath = startFilePath;
        this.startupWaitTime = startupWaitTime > 0 ? startupWaitTime : 2;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getStartFilePath() {
        return startFilePath;
    }

    public void setStartFilePath(String startFilePath) {
        this.startFilePath = startFilePath;
    }

    /**
     * 获取程序启动等待时间
     *
     * @return 启动等待时间（秒）
     */
    public int getStartupWaitTime() {
        return startupWaitTime;
    }

    /**
     * 设置程序启动等待时间
     *
     * @param startupWaitTime 启动等待时间（秒），如果小于0则使用默认值2秒
     */
    public void setStartupWaitTime(int startupWaitTime) {
        this.startupWaitTime = startupWaitTime > 0 ? startupWaitTime : 2;
    }

    public List<Step> getSteps() {
        return steps;
    }

    public void setSteps(List<Step> steps) {
        this.steps = steps;
    }

    /**
     * 添加操作步骤
     *
     * @param step 要添加的操作步骤
     */
    public void addStep(Step step) {
        this.steps.add(step);
    }

    /**
     * 获取动态值映射
     *
     * @return 当前任务的动态值映射表
     */
    public Map<String, String> getDynamicValues() {
        return dynamicValues;
    }

    /**
     * 设置动态值映射
     *
     * @param dynamicValues 要设置的动态值映射表
     */
    public void setDynamicValues(Map<String, String> dynamicValues) {
        this.dynamicValues = dynamicValues;
    }

    /**
     * 获取所有需要的动态值名称
     * <p>
     * 遍历所有步骤，收集需要动态值的步骤中配置的动态值名称
     *
     * @return 包含所有需要的动态值名称的Set集合
     */
    public Set<String> getRequiredDynamicValueNames() {
        Set<String> names = new HashSet<>();
        for (Step step : steps) {
            if (step.needsDynamicValue()) {
                names.add(step.getPasteDynamicName());
            }
        }
        return names;
    }

    /**
     * 检查是否所有需要的动态值都已设置
     * <p>
     * 该方法用于在任务执行前验证所有必需的动态值是否都已经设置，
     * 确保任务可以正常执行。
     *
     * @return 如果所有必需的动态值都已设置则返回true，否则返回false
     */
    public boolean areAllDynamicValuesSet() {
        if (dynamicValues == null) {
            dynamicValues = new HashMap<>();
        }

        Set<String> requiredNames = getRequiredDynamicValueNames();
        for (String name : requiredNames) {
            if (!dynamicValues.containsKey(name) || dynamicValues.get(name) == null || dynamicValues.get(name).isEmpty()) {
                return false;
            }
        }

        return true;
    }

    /**
     * 设置动态值
     *
     * @param name  动态值名称
     * @param value 动态值内容
     */
    public void setDynamicValue(String name, String value) {
        if (dynamicValues == null) {
            dynamicValues = new HashMap<>();
        }
        dynamicValues.put(name, value);
    }

    /**
     * 获取指定名称的动态值
     *
     * @param name 动态值名称
     * @return 对应的动态值内容，如果不存在则返回null
     */
    public String getDynamicValue(String name) {
        if (dynamicValues == null) {
            return null;
        }
        return dynamicValues.get(name);
    }

    /**
     * 清除所有动态值
     * <p>
     * 用于任务执行完成后的清理工作，或在需要重新设置所有动态值时使用
     */
    public void clearDynamicValues() {
        if (dynamicValues != null) {
            dynamicValues.clear();
        }
    }
}
